package com.example.train.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import com.example.train.model.SysPermission;
import com.example.train.model.SysRole;
import com.example.train.model.SysRolePermissionRelation;
import com.example.train.service.SysPermissionService;
import com.example.train.service.SysRolePermissionRelationService;
import org.springframework.stereotype.Service;
import com.example.train.mapper.SysPermissionMapper;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SysPermissionServiceImpl implements SysPermissionService {

    @Resource
    private SysPermissionMapper sysPermissionMapper;
    @Resource
    private SysRolePermissionRelationService sysRolePermissionRelationService;

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public int deleteByPrimaryKey(Long id) {
        sysRolePermissionRelationService.deleteByPermissionId(id);
        return sysPermissionMapper.deleteByPrimaryKey(id);
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Integer insert(SysPermission record) {
        SysPermission temp = selectByName(record.getName());
        if (temp != null) {
            return null;
        }
        if (record.getPid() == null) {
            record.setPid(0L);
        }
        record.setCreateTime(new Date());
        int count = sysPermissionMapper.insert(record);

        //直接插入，新增不需要考虑重复问题
        if (CollUtil.isNotEmpty(record.getRoles())) {
            handleRoleInsert(record);
        }
        return count;
    }

    @Override
    public int insertSelective(SysPermission record) {
        return sysPermissionMapper.insertSelective(record);
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public int updateByPrimaryKeySelective(SysPermission record) {

        List<SysRolePermissionRelation> relations = sysRolePermissionRelationService.selectByPermissionId(record.getId());
        List<SysRole> roles = record.getRoles();

        if (CollUtil.isNotEmpty(relations)) {
            //已经不存在的role删掉
            for (SysRolePermissionRelation relation : relations) {
                boolean present = roles.stream().anyMatch(l -> l.getId().equals(relation.getRoleId()));
                if (!present) {
                    sysRolePermissionRelationService.deleteById(relation.getId());
                }
            }
            if (CollUtil.isNotEmpty(roles)) {
                //新增的role保存，已经存在的过滤，不再插入
                List<SysRolePermissionRelation> collect = roles.stream()
                        .filter(r -> relations.stream().noneMatch(l -> l.getRoleId().equals(r.getId())))
                        .map(l->new SysRolePermissionRelation(l.getId(), record.getId()))
                        .collect(Collectors.toList());

                if (CollUtil.isNotEmpty(collect)) {
                    sysRolePermissionRelationService.insert(collect);
                }
            }
        }else{
            //不存在已有role,直接插入
            handleRoleInsert(record);
        }
        return sysPermissionMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(SysPermission record) {
        return sysPermissionMapper.updateByPrimaryKey(record);
    }

    @Override
    public List<SysPermission> selectByPrimaryKeys(List<Long> ids) {
        return sysPermissionMapper.selectByPrimaryKeys(ids);
    }

    @Override
    public SysPermission selectByName(String name) {
        return sysPermissionMapper.selectByName(name);
    }

    @Override
    public List<SysPermission> selectAll(List<Long> ids) {
        List<SysPermission> list = sysPermissionMapper.selectAll(ids);
        if (CollUtil.isNotEmpty(ids)) {
            List<Long> collect = list.stream().filter(l -> list.stream().noneMatch(r -> l.getPid().equals(r.getId())))
                    .map(SysPermission::getPid)
                    .collect(Collectors.toList());

            if (CollUtil.isNotEmpty(collect)) {
                List<SysPermission> parentList = selectByPrimaryKeys(collect);
                list.addAll(parentList);
            }

        }
        return list;
    }

    @Override
    public List<Tree<Long>> getPermissionList() {
//        List<SysRole> sysRoles = sysRoleMapper.selectByAdminID(adminID);
//        List<Long> roleIDs = sysRoles.stream().map(r->r.getId()).collect(Collectors.toList());
//        List<SysPermission> permissionList = sysPermissionMapper.getPermissionList(roleIDs, adminID);

        List<SysPermission> permissionList = sysPermissionMapper.selectAll(null);

        List<TreeNode<Long>> nodeList = new ArrayList<>();
        for (SysPermission p : permissionList) {
            TreeNode<Long> treeNode = new TreeNode(p.getId(),p.getPid(),p.getName(),p.getSort());

            Map<String, Object> map = new HashMap<>();
            map.put("value", p.getReqUrl());
            map.put("method", p.getReqMethod());
            map.put("icon", p.getIcon());
            map.put("type", p.getType());
            map.put("component", p.getVueComponent());
            map.put("status", p.getStatus());
            map.put("sort", p.getSort());
            map.put("createTime", p.getCreateTime());
            map.put("roles", p.getRoles().stream().map(l->{
                Map<String, Object> m = new HashMap<>();
                m.put("id", l.getId());
                m.put("name", l.getName());
                m.put("status", l.getStatus());
                return m;
            }).collect(Collectors.toList()));
            treeNode.setExtra(map);

            nodeList.add(treeNode);
        }

        List<Tree<Long>> treeList = TreeUtil.build(nodeList, 0L);

        return treeList;
    }

    private void handleRoleInsert(SysPermission record){
        if (CollUtil.isNotEmpty(record.getRoles())) {
            List<SysRolePermissionRelation> collect = record.getRoles().stream()
                    .map(l -> new SysRolePermissionRelation(l.getId(),record.getId()))
                    .collect(Collectors.toList());

            sysRolePermissionRelationService.insert(collect);
        }
    }
}
